package myjwt

import (
	"fmt"
	"github.com/golang-jwt/jwt/v4"
	"go-exp/pkg/ctxdata"
)

func GenToken(secretKey string, claims ctxdata.AuthClaims) (string, error) {
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims = claims

	return token.SignedString([]byte(secretKey))
}
func ParseAndValidateToken(tokenString string, jwtSecretKey string) (*ctxdata.AuthClaims, error) {
	claims := &ctxdata.AuthClaims{}

	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		// 1. 验证签名算法是否是你期望的
		//    DON'T PANIC! 这是重要的安全检查，防止攻击者传入 "none" 算法或其他弱算法
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}

		// 2. 返回你的密钥
		//    对于 HMAC 算法，密钥是 []byte 类型
		//    对于 RSA/ECDSA，这里应该返回 *rsa.PublicKey 或 *ecdsa.PublicKey
		return []byte(jwtSecretKey), nil
	})

	if err != nil {
		// myjwt.ParseWithClaims 会处理很多错误情况:
		// - Token 格式错误 (myjwt.ErrTokenMalformed)
		// - Token 过期 (myjwt.ErrTokenExpired)
		// - Token 尚未生效 (myjwt.ErrTokenNotValidYet)
		// - 签名无效 (myjwt.ErrTokenSignatureInvalid)
		// - 其他 ValidationError
		// 你可以使用 errors.Is() 来检查特定的错误类型
		// 例如: if errors.Is(err, myjwt.ErrTokenExpired) { ... }
		return nil, fmt.Errorf("failed to parse token: %w", err)
	}

	// 3. 检查 Token 是否有效
	//    虽然 ParseWithClaims 在 err == nil 时通常意味着 token.Valid == true，
	//    但显式检查一下是个好习惯，或者依赖 ParseWithClaims 的错误处理。
	//    根据库的文档，如果 `err` 是 `nil`，`token.Valid` 应该是 `true`。
	if !token.Valid {
		return nil, fmt.Errorf("token is invalid")
	}

	// Token 有效，claims 已经被填充
	return claims, nil
}
